home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-05-24 | 88.5 KB | 2,267 lines |
-
- The Cracking Manual
- ─────────────────────────────────────────────────────────────
- Written By The Cyborg - April 3, 1992
-
-
-
-
-
-
-
- Disclaimer
- The author of this text shall hold no liability for special,
- incidental, or consequential damages arising out of or
- resulting from the use/misuse of the information in this
- file.
-
-
-
-
-
-
-
-
- The Cracking Manual
-
-
-
- INTRODUCTION
-
- Introduction
- ------------
- Welcome to the wonderful world of cracking. What is
- cracking? If you don't know and you're reading this, ask
- yourself why? Anyway, cracking is the art of removing copy
- protected coding from programs. Why do this? In recent
- years, software companies have been fighting to keep copy
- protection in their software to avoid their work to be
- illegally copied. Users feel that such copy protection is
- ridiculous in that it violate their own rights to make
- backups of their sometimes expensive investments.
- Whichever side you may favor, this manual will go into
- some detail on removing copy protection from programs. If
- you feel offended by this, then I would suggest you stop
- here. Please note, I do not endorse cracking for the illegal
- copying of software. Please take into consideration the hard
- work and effort of many programmers to make the software.
- Illegal copying would only increase prices on software for
- all people. Use this manual with discretion as I place into
- your trust and judgement with the following knowledge.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 1
-
-
-
-
-
- The Cracking Manual
-
-
-
- WHAT YOU WILL NEED
-
- What You Will Need
- ------------------
- Like all programming, cracking is the debugging stage of
- software development. It is the most tedious and hectic part
- of programming as you shall see. However, unlike software
- development, you are given no source code, only the machine
- level code commonly called machine language. Cracking
- demands patience. No patience, no cracking.
- Before we begin, you will need certain tools. These
- include:
-
- - A decent computer. By this, I mean at minimum a 286
- computer with 2 or more megs of RAM. A 386 is the
- ideal since it can load a debugger into usable memory.
- - A source level debugger (eg. Turbo Debugger)
- - A low level debugger (eg. DEBUG)
- - An assembler system (eg. MASM, LINK, EXE2BIN)
- - A hex dumping program (eg. Norton Utilities)
-
- The source level debugger is what you will try to be using
- most of the time. It provides many features that are a
- convenience to the cracker, such as interrupt redirection.
- Become comfortable with its features. However, in some
- instances, the source level debugger may not be suitable for
- cracking huge games since the debugger itself may take up too
- much memory. In such a case, a low level debugger must be
- used since their memory usage may be considered negligible.
- This manual will focus on its use.
- The assembler package will be used in the creation of
- the famed loaders, which provide the cracker with dynamic
- memory alterations without changing the original program.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 2
-
-
-
-
-
- The Cracking Manual
-
-
-
- CRASH COURSE IN ASSEMBLY LANGUAGE
-
- Crash Course in Assembly Language
- ---------------------------------
- If you are already well familiar with the assembly
- language, you may wish to skip this section. Cracking
- demands the knowledge of assembly language. If you wish to
- become a "serious" cracker, you might like to read up more
- about this fascinating language. This section will only give
- you enough info for intermediate level cracking.
- At this point, you should familiarize yourself with
- DEBUG and its commands as we will be using them shortly.
-
- Registers
- ---------
- One of the neato things that you will be fooling around
- most often with are called the registers. Registers are like
- variables (such as in BASIC) that are located within the CPU
- itself. These registers may hold a positive integer from 0
- to 255 or from 0 to 65535. They can also hold negative
- integers from -128 to 127 or from -32768 to 32767. The
- registers are given names as follows:
-
- AX => accumulator - this register is most commonly used
- for mathematical or I/O operations
- BX => base - this register is used commonly as a base or
- a pointer register (we'll talk more about this
- later)
- CX => count - used commonly for counting instructions
- such as loops
- DX => displacement - much like the base register
-
- The registers stated above are considered general purpose
- registers, since they can basically be used to store whatever
- the user wants. Let's try putting some number in these
- registers. Type in "R {enter}". You should see a bunch of
- info, of which are four of the above mentioned registers.
- Now, type in "RAX {enter}". Then type in a number like
- 8FABh. Type in "R" again and noticed how the accumulator
- (AX) has change its number.
- These general purpose registers can also be "split" in
- half into its higher and lower order components. Instead of
- having one register AX, you can have two registers, AH and
- AL. Note however that while you have a range of 0 to FFFFh
- for AX, you will now have a range of 0 to FF for AH and AL.
- You cannot change these directly in debug, but be aware that
- programs will use it. If AX contains 0A4Ch, then AH will
- contain 0Ah and AL will contain 4Ch.
- The following are called the segment registers:
-
- CS => code segment - the block of memory where the code
- (instructions are located)
- DS => data segment - the block of memory where data can
- be accessed. In block move operations in which
-
-
- Page 3
-
-
-
-
-
- The Cracking Manual
-
-
-
- huge blocks of memory are moved, this is commonly
- the segment in which the CPU reads from.
- ES => extra segment - also another data segment. In
- block move operations in which huge blocks of
- memory are moved, this is commonly the segment in
- which the CPU writes to.
- SS => stack segment - this is the block of memory in
- which the CPU uses to store return addresses from
- subroutines. (more on this later)
-
- In introductory level of cracking, we don't mess around with
- these registers. Later, we will see how we can use these to
- trick a program into thinking other things, but that's later.
- You can also change these registers in debug. Type in "RCS
- {enter}". Then enter "0 {enter}" and notice how the CS
- register changed.
- There are other registers that we use to see what the
- program is doing. These registers can also be change in
- debug. Included are the following:
-
- SI => source index - this register is used in
- conjunction with block move instructions. This is
- a pointer within a segment (usually DS) that is
- read from by the CPU.
- DI => destination index - this register is also used in
- conjunction with block move instructions. This is
- a pointer within a segment (usually ES) that is
- written to by the CPU.
- BP => base pointer - a pointer used commonly with the
- stack segment
- SP => stack pointer - another pointer used commonly with
- the stack segment (this one, you don't touch)
-
- By now, you may probably be confused about this
- segment/pointer bit. Here is an analogy that my straighten
- things out.
- Pretend you are in kindergarden learning to read. There
- are four black boards surrounding the room. These black
- boards are like SEGMENTS. Let's pretend the front blackboard
- is the code segment (CS). The teacher has written some
- instructions on pronunciation rules. This is what the
- students refer to when they try to pronounce words. In a
- program, this is what the CPU refers to when it follows
- directions.
- Okay, now the teacher has gone to the blackboard on the
- left of the classroom. We will call this board the data
- segment (DS). The teacher has also written a set of words on
- the board. Then she uses a wooden stick or a POINTER to
- point to a word. Let's pretend this stick is the source
- index (SI). She points to the word "their". Now, the
- students look at the front blackboard (CS) to see how to
- pronounce the word and they say "their".
- Now, the instructor wants the students to learn how to
- write. She points the stick to the word "apple". The
-
-
- Page 4
-
-
-
-
-
- The Cracking Manual
-
-
-
- students pronounce the word. Then she goes to the blackboard
- on the right. We shall call this one the extra segment (ES).
- She then uses her finger as a different POINTER and points to
- a location on the board where Mary Jane will write "apple".
- That's basically what segments and pointers are.
- Segments are the blackboards and pointers are the teacher's
- stick (we're not talking sexually here) or finger.
- One last important register is the flags register.
- These registers control how certain instruction work, such as
- the conditional jumps (in BASIC, they are like IF-THEN's).
- They are stored as bits (0's or 1's) in the flags register.
- We will most often use:
-
- zero => ZR/NZ (zero/not zero) - tells you whether an
- instruction (such as subtraction) yielded a zero
- as an answer
- sign => NG/PL (negative/positive) - tells you whether an
- instruction yielded a positive or negative
- number
- carry => CY/NC (carry/no carry) - tells you whether an
- instruction needed to carry a bit (like in
- addition, you carry a number over to the next
- digit). Various system (BIOS) functions use
- this flag to denote an error.
- direction => DN/UP (decrement/increment) - tells a block
- instruction to either move forward or backwards
- in reads and writes
-
- Try changing some of these bits. Type in "RF {enter}". Then
- type in "DN {enter}" to change the direction flag to its
- decrement position.
-
- The Instructions
- ----------------
-
- MOV - move
- ----------
- Now we get to the actual instructions or commands that
- the CPU will use. The first instruction you will see most
- often is the move instruction. Its form is
- MOV {destination},{source}. Let's try programming now. Exit
- (q) and reenter debug again. Now, type in "A {enter}". You
- will see a bunch of number to the left. You can think of
- these as line numbers. Now type in "MOV AX,7A7A {enter}".
- Then type "MOV DX,AX" and so on until your program looks
- similar to the one below: (type "U 100" to see)
-
- xxxx:0100 B8A77A MOV AX,7AA7
- xxxx:0103 89C2 MOV DX,AX
- xxxx:0105 B90000 MOV CX,0000
- xxxx:0108 88D1 MOV CL,DL
- xxxx:010A 890E0005 MOV [0500],CX
- xxxx:010E 8B160005 MOV DX,[0500]
- xxxx:0112 BB0200 MOV BX,0002
-
-
- Page 5
-
-
-
-
-
- The Cracking Manual
-
-
-
- xxxx:0115 26A30005 MOV ES:[0500],AX
-
- Press enter again until you see the "-" prompt again. You
- are ready to run your first program. Type "R {enter}" and
- note the values of the general purpose registers. Then type
- in "T {enter}". Debug will automatically display the
- registers after the execution of the instruction. What is in
- the AX register? It should be 7AA7h. Now, "T" again. What
- is in the DX register? It should also be 7AA7h. Trace again
- using "T" and note that CX should be 0 if it was not already.
- Trace again and note what is in the CX register. It should
- be 00A7h. Now trace another step. What is this instruction
- doing? It is now moving the contents of CX into memory
- location 500h in the data segment (DS). Dump the memory by
- typing in "D 500". The first two two-digit numbers should be
- the same as in the CX register. But wait a minute you say.
- They are not the same. They are backwards. Instead of
- 00A7h, it is A700h. This is important. The CPU stores 16
- bit numbers in memory backwards to allow for faster access.
- For 8 bit numbers, it is the same. Now, continue tracing.
- This instruction is moving the memory contents of address
- 500h into the DX register. DX should be 00A7h, the same as
- CX regardless of how it looked in memory. The next trace
- should be nothing new. The next trace again moves the
- contents of a register into memory. But notice it is using
- the BX register as a displacement. That means it adds the
- contents of BX and 500h to get the address, which turns out
- to be 502h. But also not the "ES:" in front of the address.
- This additional statement tells the CPU to use the extra
- segment (ES) rather than the data segment (DS which is the
- default). Now dump address 502h by entering "D ES:502" and
- you should see A77Ah, which is backwards from 7AA7h.
-
- CMP/J? - compare/conditional jump
- ---------------------------------
- Another instruction you will see quite often is the CMP
- or compare instruction. This instruction compares the two
- "variables" and changes the flags register accordingly. The
- source and destination operands are the same as those for the
- move instruction.
- Let's consider an example in which the AX register holds
- 21 and the BX register holds 22. Then "CMP AX,BX" is
- performed. The compare instruction is like a subtraction
- instruction, but it doesn't change the contents of the AX
- register. So, when 22 is subtracted from 21, the answer will
- be -1, but we will never see the answer, only the flags which
- have resulted from the operation. Number 21 is less than 22,
- so the carry flag and the sign flag should be set. Just
- remember that when the carry flag is set, the first number is
- less than the second number. The same is true for the sign
- flag. Why have two flags if they tell us the same thing?
- This is more complicated and you should not concern yourself
- with it. It requires knowledge of hexadecimal arithmetic,
- the denotation of signed and unsigned integers.
-
-
- Page 6
-
-
-
-
-
- The Cracking Manual
-
-
-
- So, now that we have done the compare instruction, there
- will most likely be a conditional jump instruction after. If
- we wanted to jump if AX is less than BX (which it is), then
- there would be an instruction like "JB 200". This
- instruction says Jump if Below to instruction 200h. What
- about if we wanted to jump if AX is greater than BX. Then we
- might have "JA 200". This is read Jump if Above to
- instruction 200. What about AX equal to BX. We would then
- have "JZ 200" or "JE 200". (Please note that the previous
- instructions are synonymous.) This is read Jump if Equal to
- instruction 200h. Here are the jumps you will most likely
- encounter:
-
- Mnemonic Flag(s) Checked Description
- -------------------------------------------------------------
- JB/JNAE CF=1 Jump if below/not above or
- equal (unsigned)
- JAE/JNB CF=0 Jump if above or equal/not
- above (unsigned)
- JBE/JNA CF=1 or ZF=1 Jump if below or equal/not
- above (unsigned)
- JE/JZ ZF=1 Jump if equal/zero
- JNE/JNZ ZF=0 Jump if not equal/not zero
- JL/JNGE SF not equal Jump if less/not greater or
- to OF equal (signed)
- JGE/JNL SF=OF Jump if greater or equal/not
- less (signed)
- JLE/JNG ZF=1 or SF Jump is less or equal/not
- not equal OF greater (signed)
- JG/JNLE ZF=0 or SF=OF Jump if greater/not less or
- equal (signed)
- JS SF=1 Jump if sign
- JNS SF=0 Jump if no sign
- JC CF=1 Jump if carry
- JNC CF=0 Jump if no carry
- JO OF=1 Jump if overflow
- JNO OF=0 Jump if not overflow
- JP/JPE PF=1 Jump if parity/parity even
- JNP/JPO PF=0 Jump if no parity/parity odd
-
- There are all the possible combinations of conditional jumps
- that you will encounter. I realize that we have not
- discussed some of the flags such as overflow or parity, but
- be aware that they exist and programs sometimes use them.
-
- JMP - jump
- ----------
- This instruction does what it suggests. It jumps too
- different sections of code. Several forms of the jump
- instruction include:
-
- 2E0B:0208 EBF6 JMP 0200
- 2E0B:020A 3EFF24 JMP DWORD PTR DS:[SI]
-
-
-
- Page 7
-
-
-
-
-
- The Cracking Manual
-
-
-
- The first instruction jumps to an address within the segment.
- The latter instruction jumps to an address pointed to by ds:
- si. The DWORD says that this will be a far jump, a jump to a
- different segment (a different blackboard). So, if the
- double word that is pointed to by ds:si contains 1000:0040h,
- then, the instruction will jump to 1000:0040h whereas the
- previous jump instruction will jump within the current
- segment (or blackboard).
-
- CALL - procedural transfer
- --------------------------
- This instruction is the baby that you will be carefully
- watching out for most often. This instruction calls another
- procedure and upon it's completion, will return to calling
- address. For example, consider the following block of code:
-
- 2E0B:1002 E8BB46 CALL 56C0
- 2E0B:1005 7209 JB 1010
- 2E0B:1007 0C00 OR AL,00
-
- The first line calls another procedure at "line number"
- 56C0h. Upon its completion, the instruction pointer will
- point to the second line. Note that there is a "JC"
- instruction. Remember that programs often use the carry flag
- to signal errors. If the call instruction called a copy
- protection instruction and you entered a wrong code or
- something, it may return with the carry flag set. The next
- instruction would then jump if there was an error to an
- exiting procedure.
- Note, this is a near call. A program can also have far
- calls just like jumps.
-
- INT - generate an interrupt
- ---------------------------
- This instruction is much like the call instruction. It
- also transfers control to another procedure. However, the
- number after the INT instruction does not point to an
- address. Instead, it is a number pointing to an address that
- is located in something called an interrupt vector. You will
- commonly see "INT 10", "INT 21", "INT 13". Just know (for
- now) that they are like calls to procedures.
-
- LODSB/LODSW/STOSB/STOSW - load/store a byte/word
- ------------------------------------------------
- These instructions either load in or store a byte or a
- word to or from memory. The DS:SI register pair points to
- the source data. These are the registers the CPU will use
- when reading from memory using the LODS instruction. The
- AX/AL register will hold the number to either read from or
- write to the memory. So, if DS:SI points to a byte which is
- maybe 60, then a "LODSB" instruction will load in the number
- 60 into the AL register. A LODSB or STOSB will use the AL
- register while the LODSW or STOSW will use the AX register.
- The STOS writes whatever is in the AX/AL register to the
-
-
- Page 8
-
-
-
-
-
- The Cracking Manual
-
-
-
- memory pointed to by ES:DI. So, if ES:DI points to 100:102h
- and if AL held 50, then the byte at 100:102h will hold 50.
- After the instruction is finished, the CPU will either
- increment or decrement SI or DI according to the status of
- the direction flag. So, if SI was 100h and a "LODSW"
- instruction was performed with a cleared direction flag
- (forward), the SI will now point to 102h.
-
- MOVSB/MOVSW - copies a byte/word from source to destination
- -----------------------------------------------------------
- This instruction gets a byte or a word from the data
- pointed to by DS:SI and copies it to the data pointed to by
- the ES:DI address. When the instruction is finished, SI and
- DI will be incremented or decremented accordingly with the
- status of the direction flag. So, if DS:SI pointed to a byte
- with the number 30, a "MOVSB" instruction would copy into the
- byte pointed to by ES:DI the number 30.
-
- REP - repeat
- ------------
- The REP instruction in front of a MOVS/LODS/STOS would
- cause the MOVS/LODS/STOS instruction to be repeated for a
- number of times specified in the CX register. So, if CX
- contained 5, then "REP STOSB" would store whatever was in the
- AL register into the byte pointed to by ES:DI five times,
- increasing DI each time.
-
- LOOP - looping
- --------------
- The LOOP instruction repeats a block of instructions for
- a certain number of times. This number will be held in the
- CX register. Each time we reach this instruction, the CPU
- will decrement the CX register and jump to a specified
- instruction until CX becomes zero. This instruction looks
- like "LOOP 1A00" where the number indicates the instruction
- address to loop to.
-
- Arithmetic Operators
- --------------------
- Arithmetic instructions allow you to perform various
- arithmetic function of data. "ADD" and "SUB" work the same
- way as "MOV" instructions do in that it subtracts whatever is
- in the source register from the destination register and
- stores it in the destination register.
- The "MUL" and "DIV" instructions are a bit more
- complicated and they are not used as intensively as the "ADD"
- or "SUB" since they are slow, so we will not talk about them.
- There are also a multitude of other instructions that
- you should familiarize yourself with if you are thinking of
- becoming a serious cracker. The instructions given above are
- only the BARE minimum that you need. There is no way around
- learning assembly for better cracking.
-
-
-
-
- Page 9
-
-
-
-
-
- The Cracking Manual
-
-
-
- THE CRACKING
-
- The Cracking
- ------------
- Now the fun stuff begins. First, we must discuss the
- different forms of copy protection schemes. They are
- basically divided into the disk based and manual based copy
- protection schemes.
- With disk based schemes, the software often reads from
- specific sectors on a disk to determine the disk's validity.
- How can this be done? When you perform a disk format, the
- disk is formatted with specific sector sizes. Once the
- sector size changes, DOS cannot recognize it, thinking that
- it is a bad sector. Since this looks like a bad sector, a
- simple DISKCOPY will not work in copying such disks.
- Interrupt 13h (the assembly mnemonic is INT 13) was commonly
- used to handle such copy protections. It is now very rare to
- encounter the once famed INT 13h copy protection method
- nowadays since it was quite easy to defeat. Any professional
- commercial software will often use their own custom based
- disk I/O routines. This involves intimate access to I/O
- ports using IN and OUT instructions. This is beyond the
- scope of the first release of this manual. However, if you
- are lucky, the I/O functions might be called from a "CALL"
- instruction in which case you may defeat the protection
- without much difficulty. Another disk based scheme used to
- denote legality of software is used during the installation
- process of the software. With certain programs, when you
- install it, it copies the files into the hard drive. But it
- also sets a specific sector in the hard drive so that the
- program can recognize it. This is also similar to diskette
- copy protections, but can be defeated in much the same way.
- Thank goodness that disk based copy protections are
- almost completely out of the software industry. However, a
- sometimes more difficult copy protection scheme has arisen
- that may sometimes prove to be even more difficult to crack.
- These schemes are commonly known as the doc checks in which
- the user must have a copy of the manual to bypass the
- protection. With programs compiled as true assembly (you can
- call then "normal" programs), these protections are not too
- bad to trace through and crack. With programs that run
- scripts (such as Sierra games), this can he a real chore
- however. Why? It is because it is like running a program
- within a program. You just have to be very very patient in
- this case, carefully tracing through the instructions.
- As if these copy protection schemes weren't enough,
- software companies have also added trace inhibition schemes
- to their code. What does this mean? This means that you
- will have a hell of a time trying to trace through code.
- However, if you know how these things work, it should not be
- too much of a problem.
- Run-time compression/decompression and
- encryption/decryption of files also make changes to the
- program difficult. In this case, the loader sure comes in
-
-
- Page 10
-
-
-
-
-
- The Cracking Manual
-
-
-
- handy. Also, when the data within the file changes due to
- overlays, loaders are also good to use.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 11
-
-
-
-
-
- The Cracking Manual
-
-
-
- DISK BASED COPY PROTECTIONS
-
- Disk Based Copy Protection
- --------------------------
- Since disk based copy protection schemes are rarely
- used, we will not go into great depth in its discussion.
-
- INT 13h
- -------
- I have previously mentioned that INT 13h copy protection
- schemes are hardly ever used anymore. Nevertheless, it would
- be good practice for the beginner to learn how to defeat the
- code. You will most likely see INT 13h used with function 2,
- read sector. This means that:
-
- AH => will contain the number 2 (function 2)
- AL => the number of sectors to read in. This is
- commonly only 1 since you just want to check a few
- sectors for disk validity.
- CH => will contain the cylinder number
- CL => will contain the sector number
- DH => will contain the head number
- DL => will contain the drive number
- 00h - 7Fh for floppies
- 80h - FFh for fixed disks
- ES:BX => will point to the address into which the data
- read from the disk will be written to
-
- Upon the return for this interrupt, if the carry flag is
- set, that means that the program could not read the sector,
- and therefore the disk is valid. If the carry flag is clear,
- that meant that INT 13h could read the sector properly and so
- the disk would be bad in the eyes of the program, thinking it
- was a copied disk.
- Okay, now that we know to look for INT 13h in the
- program code, we can begin tracing. First, we must know the
- difference between debug's "T" and "P". "T" is the trace
- instruction, which tells it to follow instructions step by
- step. That also means that in LOOP or REP instruction, the
- trace will patiently go through the loop until finished.
- Also, during CALL instructions, trace will go into the call
- and execute the instructions pointed to by the call
- instruction. The "P" command is similar to the "T" but with
- the difference in that it traces over instructions. That
- means that if it encounter a LOOP or REP, it will quickly
- finish up the loop and point to the next instruction. With a
- CALL, the "P" (proceed) will not go into the subroutine.
- Instead, it will just execute the procedure, then point to
- the next instruction.
- Okay, before you start tracing for hours through a
- program, you must first notice when and where the copy
- protection appears. Run the program in DOS first and make
- careful note of when things happen. You might see an intro
- screen, then the music pops up, then the menu comes out.
-
-
- Page 12
-
-
-
-
-
- The Cracking Manual
-
-
-
- Notice this so you will know where you are in the program.
- Once you have done that, you can begin debugging the
- program. Whenever you start out with a program, you use "P"
- to trace through the program. Be patient as this might take
- a while. While you are tracing, watch out for CALLs and
- INTerrupts. When you are just about to execute the step, try
- to remember the segment and offset of the instruction. The
- segment is the number to the left of the colon while the
- offset is the number to the right. As you continue tracing
- through the program, you will find that the screen might
- blank and display the intro screen or something like that.
- This is a good sign and it tells you that you are headed in
- the right direction. Start slowing down when you feel that
- you are near to the copy protection.
-
- Situation 1 - Exit from copy protected CALL
- -------------------------------------------
- Oops, you have traced over a call that accessed drive A.
- Unfortunately, you also exited the program. That's good.
- You have just narrowed down the location of the copy
- protection code. Now I hope you remembered the address of
- that CALL. If not, you gotta start all over to find it.
- Anyway, restart the program now. Now Go to that instruction
- by "G {segment:address}".
- Did something go wrong? Did the computer freeze or
- something? It is most likely that this is an overlay or
- encrypted code or something that caused the code at that
- location to change. In this case, you will have to remember
- the addresses of various instructions along the way.
- Instructions that you want to take note of are far calls (if
- you remember, calls with a segment:offset address as their
- operand). You don't have to do this for every call. As you
- crack more and more, you will get the hang of which
- instructions to keep track of.
- Okay, let's assume you have gotten back into the
- location of the code again. It is a CALL instruction that
- will access the disk drive. At this point, try skipping the
- CALL instruction. To do this, type in "RIP {enter}". Then
- type in the address of the next instruction. Then execute
- the do or die instruction, "G". If the program runs fine
- without asking for the copy protection, congratulations! You
- have cracked the program.
- If the program freezes or does something weird, restart
- the program and trace back to the suspected copy protected
- location. Now use the "T" command once and start using "P"
- again. Remember to write down the address of that CALL
- instruction you just traced into so you can come back to it
- quickly. As you keep tracing, using the above procedures,
- pretend you eventually come up to an INT 13h instruction.
- See what it does by tracing over it. Make sure you have a
- disk in drive A too. If there was no error, force an error
- by turning on the carry flag and proceeding. With INT 13h
- copy protections, this should be sufficient to crack the
- program.
-
-
- Page 13
-
-
-
-
-
- The Cracking Manual
-
-
-
- Situation 2 - Return from copy protected CALL
- ---------------------------------------------
- Okay, the CALL that you just traced over accessed the
- disk drive, but it didn't kick you out. Keep on proceeding
- and this point. If there is an instruction that causes you
- to jump because of a carry flag, try fooling around with this
- carry flag and see how the program reacts. INT 13h copy
- protections are usually simple enough for you to just change
- the carry flag to allow the program to bypass the copy
- protection.
-
- Access to the Hard Drive
- ------------------------
- The cracking for installation software is also the same
- as cracking for the INT 13h. You just keep tracing until you
- see some disk activity. At that point, you try messing
- around with some of the conditional jumps to see what
- happens. If you have the original program, you should run it
- also to see the differences between the valid and invalid
- copies.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 14
-
-
-
-
-
- The Cracking Manual
-
-
-
- DOC CHECK COPY PROTECTIONS
-
- Doc Check Copy Protections
- --------------------------
- Okay, we have just quickly scanned over disk based copy
- protections because they are rarely used nowadays. Doc
- checks will be discussed in greater detail for the rest of
- this manual.
- Unlike the disk based protections, which are based on
- hardware identification, doc checks are based on software
- identification. Therefore, the only information that will
- indicate that a copy protection is happening is the screen,
- unlike the whirr of the disk drive. The moral, watch the
- screen. Because this copy protection is software based, it
- will be more of a challenge to trace, but of course, that is
- the "fun" part of cracking.
-
- The Basics
- ----------
- Make sure you have the COMPLETE version of the program
- you are about to crack. When you do, run the program in DOS.
- While the program is loading, take note of exactly what goes
- on with the screens, sounds, etc. Here is what you might
- want to note:
-
- 1) What comes up first? Is it a standard text output
- that asks you for the type of graphics adaptor you
- have, the number of joysticks, the sound card?
- 2) When does the intro screen come up? Is it after the
- music starts? After the copyright notice? After
- the text prompt for the graphics mode you will be
- operating in?
- 3) What happens now? An animated sequence that brings
- you through the beginning plot of a game? If so,
- can you press a key and escape from it?
- 4) Now what? Is there a main menu? When you start the
- game by selecting the "START GAME" option from the
- menu, does the copy protection come up immediately?
- 5) If it doesn't come up immediately, when does it come
- up?
- 6) Does the copy protection only appear when you are
- playing the game, or does it come up also when you
- select "CHANGE OPTIONS" from the main menu?
-
- Obviously, these questions are merely prompts for you to
- follow. Use your own mind in discovering what to take note
- of. There are no set rules for cracking. It is a puzzle
- that you must use your mind on.
- Okay, once you have run the program, go into your
- debugger (in our case, DEBUG) and load up the program. One
- tip to use when you first start out programming is to use the
- "P" command to trace through code. As you become a more
- advanced cracker, you might start seeing patterns in coding.
- These patterns are characteristic of high level programming
-
-
- Page 15
-
-
-
-
-
- The Cracking Manual
-
-
-
- languages (Pascal, C, etc.) and are usually the
- initialization code for the rest of the program. Use "P" for
- each instruction, one at a time. Be patient as this might
- take a while.
- Okay, you have been tracing for some time now and
- finally, you notice something happen. The screen might have
- blanked or maybe a message prompting you to enter the
- graphics mode may have popped up. Was this what you have
- noted before? It should be and you can assure yourself that
- you are headed in the right direction. As you keep tracing
- programs, you notice that CALLs usually do something
- significant. A CALL might clear the screen or sound some
- music. When it does something rad like this, write down its
- address as the segment:offset pair. The segment is the
- number to the left of the colon while the offset is the
- number to the right of the colon. Don't be a dork and set a
- breakpoint there. Write it down on paper or something. We
- will see later on why breakpoints fail miserably in the cool
- wares.
- Why take note of these instructions? As you trace
- deeper and deeper into programs, the coding often loads up
- overlays or maybe decompresses code to the memory location
- that you have just traced over. Therefore, if you set a
- breakpoint there, or execute a "G" instruction to that
- address, you will fuck up the program and cause your computer
- to freeze. We will see why when we examine how breakpoints
- and single stepping works.
- Also, while you are tracing using "P", mentally remember
- the addresses of the CALLs. That way, if you trace over a
- call that brought you immediately to the copy protection, you
- won't have to retrace the code again. You don't have to
- write down all of the addresses, of course, just remember one
- at a time and write them down if they do anything
- significant.
-
- Code Guards Through Keyword Entry
- ---------------------------------
- Okay, you know that the copy protection is one in which
- the program waits for you to type in a keyword that you have
- to look up in the manual or something. Here are then
- following steps you should take.
-
- Situation 1 - Return from a copy protected CALL
- -----------------------------------------------
- When a copy protection coding reveals itself on the
- screen, you can have a situation in which you are returned to
- the debugger, waiting for the next instruction to be
- executed. Now, suppose that the CALL asked you to enter a
- code. You entered an incorrect code and were returned to the
- debugger, but you have not exited the program. Make sure
- that you have previously recorded the address of this CALL.
- Now, you can do two things, (1) you can try skipping over the
- CALL, (2) you can trace on further. As you become more
- experienced, you will be able to better decide. As one with
-
-
- Page 16
-
-
-
-
-
- The Cracking Manual
-
-
-
- experience, however, I can say that 90% of the time, you will
- have to trace further on, but hey, you might get lucky.
- For now, let's say you are lazy and decide that you want
- to skip over the call to see what happens. To do this, you
- must restart the program. Then trace your way back to the
- CALL where the copy protection was located. Use "G
- {segment:offset}" to do this. If, for some reason, the
- computer freezes when you do this, you will have to use "G"
- followed by the addresses of the CALLs that you have noted
- down to be significant. If that doesn't work, resort to
- retracing the code over again. As you become more
- experienced, you will find that you rarely have to retrace
- the entire code since you can "feel" what is going on. Okay,
- now that you are at the location of the CALL, this is the
- time to skip over the instruction. To do this, enter "RIP"
- and then the address of the next instruction's address. Now
- enter the "G" command and see what happens. If the program
- runs just fine, you've cracked the program. If the program
- kicks you out or crashes, you have to do some more tracing.
- Okay, so you've decided to continue tracing from the
- point of the copy protection. There are usually a bunch of
- CMP and J? CMPS? instructions after the call. This point on
- is the difficulty of cracking for a beginner since you don't
- know what the fuck is going on. All those compares and jumps
- don't mean shit to you are you are about to pass out in
- frustration. Don't distress, here are a few tips I can give
- you. If these don't work, you gotta find out your own
- solutions to the problem.
- Okay, in all probability, the CALL that you just traced
- over was acting as a read string procedure (like BASIC's
- INPUT). That means somewhere in the computer's memory, there
- lies the code that you typed in and the code that you were
- supposed to have typed in. What this would mean is that the
- code after the CALL will do some sort of string comparison.
- Look out for these. It might be hidden inside another CALL
- if you're lucky. In such a case, does the program kick you
- out? If it does, you have to trace into the call using "T"
- to see what is going on. Okay, the string comparison will
- most likely take the form of some kind of loop. Maybe "REP
- CMPSB" or "LOOP". In the case of the REP CMPSB, there might
- be a JZ/JNZ or JCXZ/JECXZ that follows it. When strings
- match, the CX register will be zero. If CX is not zero, the
- strings are not the same and the conditional jump will
- probably jump to an exit routine. All you have to do is to
- change the status of the zero flag. Then, try out the "G"
- instruction. If it still didn't work, start over and do some
- more tracing. If the string compare is not of the REP form,
- there will be some kind of loop that will check between two
- memory locations. In such a case, you will just have to
- become accustomed to realizing that the code is a string
- compare. There is no standard code for this. If you know
- you have entered a wrong code, trace through the loop and see
- where in the loop you are thrown out of the loop. At this
- point, you can go back to it, change some flags to make sure
-
-
- Page 17
-
-
-
-
-
- The Cracking Manual
-
-
-
- you stay in the loop. When you exit through a different
- location, you have probably bypassed the code and now, you
- can enter "G" to see what happens.
-
- Situation 2 - Exit from a copy protected CALL
- ---------------------------------------------
- When a copy protection coding reveals itself on the
- screen, you can have a situation in which you are not
- returned to the debugger, instead, causing you to exit the
- program. In this case, you have to restart the program and
- trace into the CALL using "T". After that, you can start
- using "P" again to uncover the location of the code. You
- will most likely encounter a condition that will resemble
- situation 1. Follow its instructions.
-
- Shortcuts For Keyword Entry Protections
- ---------------------------------------
- With keyword entry systems, you might be lucky to have
- the codes stuck somewhere into file in its
- uncompressed/unencrypted form. This means that you can "see"
- the keywords in its ASCII format. This case is cool because
- you won't have to do any tracing to crack the program. All
- you have to do is to dump the contents of the files to find
- something that looks like a keyword. (Always backup the file
- that you are about to alter.) When you have found such a
- file and the location of the codes, all you have to do now is
- to change the codes to values that you know. For example,
- one code might call for you to enter "PIRATE". It's a bitch
- if you don't know the code. But if you change the code to
- your name or something else you will never forget ("CYBORG"),
- then you'd be set.
- However, in most instances, you can't simple just type
- over the old code with your new code. In high level
- languages, these codes are stored as strings. In 'C',
- strings are stored in their ASCII equivalent. They are then
- terminated with a NULL character (this is a 0). In Pascal,
- the lengths of the strings are first stored in the first
- position. Then, the ASCII is stored.
-
- NULL Terminated Strings
- -----------------------
- So, if you see zeros after the codes, this is a NULL
- terminated string. Now, start at the beginning of the string
- and enter your code. Then, enter the '0'. Make sure your
- string is less than the original string since 'C' refers to
- these strings also with pointers.
-
- Pre-Length Indentifier
- ----------------------
- If you see numbers before strings, enter your own code.
- Then change the length of the code appropriately. Make sure
- you do not exceed the length of the original string.
-
-
-
-
- Page 18
-
-
-
-
-
- The Cracking Manual
-
-
-
- Code Guards Through Pointed Icons
- ---------------------------------
- We have a case where we do not type in keywords.
- Rather, we must use a pointer device such as the cursor keys
- on the keyboard, the mouse, or joystick. These protections
- are a bit more complicated since there are no strings to
- compare against. Rather, the input will be a number stored
- in memory or a register. This is what makes this copy
- protection more difficult to crack. We have to hunt through
- code to find out which compare instruction is the key.
- What you have to do is to find the general location of
- the copy protection code as before. Then, instead of typing
- in the keyword, you select the icon. Like before, you must
- step slowly through the code and go until the program JUST
- STOPS asking you for the code. For example:
-
- 2E0B:0000 E8740E CALL 0E77
- 2E0B:0003 38D0 CMP AL,DL
- 2E0B:0005 7569 JNZ 0070
- 2E0B:0007 CB RETF
-
- You might decide to trace over the call at address xxxx:0000.
- But then, you see that the screen displayed the icons and you
- got to select the code. Then, the procedure does some disk
- activity and you return to address xxxx:0003. If you see
- something happen after you have just finished entering the
- code or if it is slow in returning you to debug, then,
- some code must have been performed before you returned. In
- this case, you must trace into the CALL to see what has
- happened. If not, there is still a small probability that
- there were some instructions that formatted the code you
- entered and saved it to a memory location. (We'll talk about
- multiple doc checks later.)
- Realize that most of the programs that you will be
- cracking have been programed by C or some other high level
- language. These languages often use the stack (SS:SP) to
- pass parameters (variables) or to create local variables for
- a procedure's use. Most likely, you will see compares to
- data contained within the stack such as "CMP AX,WORD PTR
- [BP+10]" or "MOV DX,WORD PTR [BP+10]". This is what you hope
- to find, although not always the case. If you do see some
- access via the stack using the BP register as a pointer, you
- may have something there. Then, all you would have to do is
- to mess around the flags register (most likely, JZ/JE will be
- used) at the compare instruction.
-
- Multiple Doc Checks
- -------------------
- There are some wares that invoke multiple doc checks,
- doc checks that pop up either systematically or randomly. In
- addition, there could also be two types of this protection.
- The doc check could be a similar type (eg. typing the code
- found on page...) or they could be different (eg. typing in
- the code on page... then select the correct icon), although
-
-
- Page 19
-
-
-
-
-
- The Cracking Manual
-
-
-
- the latter is more rarely used due to its extensive memory
- usage.
-
- Situation 1 - Similar doc checks
- --------------------------------
- Cracking multiple doc checks that are similar is just
- like cracking with just one doc check. The procedure to
- trace is still the same. Keep Proceeding until you come up
- to the CALL that contains the copy protection. Just use the
- sequences mentioned above. When you are absolutely positive
- that the call contains the copy protection (skip the CALL and
- see what happens; if the protection has been bypassed but
- appears at other times, you got something), here is what you
- do.
-
- 1) Note what type of CALL it was. Near if the operand
- (number after the CALL) was a four digit number or
- far if the operand contained the segment:offset
- pair.
- 2) Trace INTO the call.
- 3) At the first instruction, note the address inside
- the CALL.
- 4) Then, type in "A" then the address of that very
- first instruction.
- 5) If there was a near call performed, now type in
- "RETN", otherwise, type in "RETF".
- 6) Now run the program ("G") and see what happens.
-
- If this call was definitely the copy protection, you should
- have bypassed the copy protection completely. Otherwise, you
- might have a case like situation 2.
-
- Situation 2 - Different doc check types
- ---------------------------------------
- Again, cracking multiple doc checks are like cracking
- single doc checks. You follow the same procedures until you
- come up to a copy protected location. Then, you would trace
- into the code as explained in situation 1 just to make sure
- that the code is not called up again. Different doc checks
- are a bitch to do because you have to manually keep tracing
- until you find each one to effectively rid yourself of the
- copy protection. There is not sure way of getting rid of all
- the doc checks any other way. But luckily, there are very
- few wares out there like this. Remember, the more the
- company shoves into the program's memory, the more money it's
- gonna cost them.
-
- Of course, I cannot cover every single type of doc check
- since there are too many of them. You'd just have to use
- your own imagination to solve some of them.
-
-
-
-
-
-
- Page 20
-
-
-
-
-
- The Cracking Manual
-
-
-
- SPECIAL SITUATIONS
-
- Special Situations
- ------------------
- What all crackers are faced with at one time or another
- are situations that call for intuitive thinking to overcome
- the barrier. Remember, there is no one sure way of cracking.
-
- INT 3 - Problems During Tracing
- -------------------------------
- Sometimes, when you start cracking, you just find your
- instruction pointer messing up. You keep tracing and
- tracing, then your computer freezes. But then, when you type
- "G" at the beginning of the program, it works just fine.
- What is happening here? There are several things that the
- program could do to impede tracing. Unless you have a
- hardware debugger, you have to settle in for more primitive,
- intuitive methods. First, we have to find out how a software
- debugger works.
- I now introduce you to INT 3 and INT 1. They are the
- breakpoint and single stepping interrupts respectively. We
- will be looking at INT 3 the most.
- What happens when you set breakpoints? Well, here is
- what the debugger does. At the address you have specified,
- the debugger will read in the byte at that address and store
- it somewhere else in its own memory. This byte is part of
- the whole instruction located at that address. For example,
- if there was an "INT 13" at that location, the machine
- language equivalent will be CD13h. Debug will read in the
- first byte, CDh, and save it in memory. The CDh will then be
- replaced by INT 3 (CCh). So, the code will now look like
- CC13h in machine language. When you unassemble this at the
- address, you will see "INT 3" (the instruction only takes up
- one byte) and some gibberish after that. So, when the CPU
- comes up to this address, it will encounter INT 3 and will
- return control to the debugger. The debugger then replaces
- the INT 3 with the CDh byte used before.
- With single stepping, the same thing occurs. Debug will
- also insert the INT 3 instruction at the instruction after
- the one you are about to execute. Then, internally, a "G"
- instruction is performed until it reaches the INT 3, at which
- point, the byte will be replaced and everything will be cool.
-
- Use of INT 3 to Call Up Other Interrupts
- ----------------------------------------
- This INT 3 deal seems to be cool, working in many
- situations. But what if the software vendor reprograms INT 3
- to point to an INT 21? Many programs use INT 21 to access
- DOS functions like reading a file, etc. There would be a
- conflict now as the program uses INT 3 to call up DOS while
- debug wants to use INT 3 for its breakpoints. There is also
- another problem. INT 21 uses two bytes (CD21h) while INT 3
- uses only one byte (CCh). Therefore, you cannot replace INT
- 3 with the INT 21.
-
-
- Page 21
-
-
-
-
-
- The Cracking Manual
-
-
-
- Also, INT 3 could be reprogrammed so that everytime it
- is used, the program will just exit to its higher process.
- So everytime you single step, you will be kicked out of the
- program.
-
- Parity Errors with INT 3
- ------------------------
- The tough copy protections use the change of memory to
- obstruct tracing. Examine the code below:
-
- 2E0B:0500 FC CLD
- 2E0B:0501 B80000 MOV AX,0000
- 2E0B:0504 BB0000 MOV BX,0000
- 2E0B:0507 BE0005 MOV SI,0500
- 2E0B:050A BF0010 MOV DI,1000
- 2E0B:050D B90005 MOV CX,0500
- 2E0B:0510 AC LODSB
- 2E0B:0511 345A XOR AL,5A ;'Z'
- 2E0B:0513 01C3 ADD BX,AX
- 2E0B:0515 AA STOSB
- 2E0B:0516 E2F8 LOOP 0510
- 2E0B:0518 3B1E0043 CMP BX,[4300]
- 2E0B:051C 7403 JZ 0521
- 2E0B:051E E9EF2A JMP 3010
- 2E0B:0521 D1E0 SHL AX,1
-
- Notice what the program is doing. It is performing a simple
- decryption of a block of code from address 500h and putting
- it in address 1000h. In addition, there is a checksum being
- performed at address . The program is adding all those bytes
- up, then comparing the number with some other number (a
- checksum value) in memory at address 4300h. So what you may
- say. When the program is run without any set breakpoints,
- the program will run fine. But when you start tracing
- through the code, or putting a breakpoint somewhere after the
- loop, the program will cause you to exit. If you decide to
- change the program so that it will let you pass regardless of
- the checksum value, somewhere along the line, the program
- will fuck up.
- This goes back to the idea of INT 3. Right before debug
- executes an instruction, it places an INT 3 at the next
- instruction. In this program, when debug places this
- interrupt and executes an instruction, the program is reading
- in this INT 3 at the address and copies it to a different
- address. INT 3 is obviously a different number than the
- other instructions, so the checksum value will be different.
- So, now that INT 3 is copied to another location in memory,
- debug also cannot replace that with it's original byte value.
- Therefore, if you try to force the checksum to match and
- continue running the program, the program will crash because
- the INT 3 is causing the instructions after itself to be
- interpreted incorrectly by the CPU.
- To bypass this, you have to make sure not to get your
- INT 3 placed in the wrong place at the wrong time. Looking
-
-
- Page 22
-
-
-
-
-
- The Cracking Manual
-
-
-
- at the program, you can keep tracing normally until the SI
- register points to any byte past the CMP instruction at
- address 519h. Then, you can do a "G 518" to finish off the
- loop quicker. Debug will place a temporary INT 3 at address
- 518h, but it doesn't matter now since SI will be past 518h.
- This is obviously a simple example, but it gets the point
- across that you have to watch where you trace.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 23
-
-
-
-
-
- The Cracking Manual
-
-
-
- OVERLAYS/LOADERS
-
- Overlays/Loaders
- ----------------
- Sometimes, programs will have an initialization code and
- upon its completion, call up another program or overlay.
- These programs present unique situations in which it is
- sometimes difficult, after finding the copy protection code,
- to write the changes to disk. Let's see what these programs
- do before we go on to the next topic of making changes
- permanent.
- Loaders are usually small programs that might first ask
- you for the graphics mode or what sound card you have. When
- finished, it will load up another program. Sometimes, this
- is done with DOS' interrupt 21h, function 4B00h (load and
- execute). This is the same interrupt DOS uses to load up
- programs when you type them in at the DOS prompt. You can
- tell what file is going to be executed by tracing up to the
- INT 21 instruction and dumping the address pointed to by
- DS:DX (type in "D DS:DX"). Also, internal procedures could
- be used to call up the program. Use what you've learned to
- trace through them.
- Code decryptions or dynamic heap allocation where data
- is to be loaded presents problems as well. Code that changes
- as the program progresses makes code changes difficult in the
- file itself. And when you want to alter sometime in the data
- area, something called a heap is often used to store the
- data. The thing with the heap is that it can be allocated at
- anytime and depending on what is currently in memory, you
- can't tell where the memory is going to be located. In these
- cases, you might choose to go with run-time memory overlays
- (discussed later).
-
- Writing the Changes Out to the File
- -----------------------------------
- Okay, so you've found the copy protection. You also
- know how to bypass it. Now, the next problem you will most
- likely encounter is writing it out to a file. But first,
- let's assume a simple case.
-
- Using a Hex Dump Program
- ------------------------
- Included is this package is one of the files from Norton
- Utilities which does a decent job of finding and changing the
- contents of files. Before we exit that debugger, we must
- know what to look for.
-
- 1) At the location of the instruction, copy down the
- machine language equivalent of the instruction. At
- instructions after that, also take down their
- machine level equivalents. This is what you will
- use to search for the code in the file.
- a) If there is a near call or a near jump or a near
- memory access, you can just write down all the
-
-
- Page 24
-
-
-
-
-
- The Cracking Manual
-
-
-
- hex numbers.
- b) If there is a far call (CALL DS:[5C10+BX]) or a
- far jump (JMP DWORD PTR ES:[5080+BX]) or a far
- memory access (MOV AX,WORD PTR ES:[10+SI]), then
- do not write these instructions down. In .EXE
- files, anything that is located in different
- segments will have different displacement
- values. This is a value in the file. At the
- beginning of the file is a table that tells DOS
- where these instructions are located. When the
- program is loaded into memory, the pointers are
- changed appropriately to match the memory
- location. So, write down other near
- instructions like CLD, JZ 100, INC AX, etc.
- 2) After you know what to search for, you must now know
- what you will have to be changing. Very often,
- NOP's are used to "delete" code. For example, if
- there is a CALL 3140 and we want to skip this call,
- we can NOP it out. The near call takes up three
- bytes. The NOP takes up one byte. So, type in "A"
- at the address of the call and enter "NOP" three
- times. Then unassemble the code to make sure that
- the code still looks okay. Take down the machine
- level equivalents of the NOP's (90h). Same thing
- with conditional jumps. Suppose you have a JZ 90
- and you want it to jump to address 90 everytime,
- then type in "A" at the jump instruction and enter
- "JMP 90". Then, just write down the machine code as
- before. One thing, however. You cannot do what I
- have just said above with far calls. Remember, the
- numbers will be different in the file as compared to
- memory. So what do you do? No problemo. At the
- call instruction, trace into the call and place a
- "RETF" instruction at the address of the callee.
- This will be the location that you will search for
- (write down the bytes here) and where you will be
- writing to (RETF is CBh in machine language).
- 3) Finally, after all this is through, you can enter
- your file editor and search for the numbers you
- wrote down. Then, you can change the numbers. Now
- run the program and it should be cracked. But
- remember, always backup the file you are about to
- change.
-
- Using a Memory Overlay
- ----------------------
- When do you use these things? You would use memory
- overlays when step 3 (stated above) has failed in some way.
- Maybe you couldn't find the code, or when you change it, the
- program freezes up. Don't fret, the memory overlay is here.
- What is a memory overlay? It is an external program (TSR)
- that when it reaches a certain point during program
- execution, it will change the location in memory you have
- specified. It overlays the code during run time.
-
-
- Page 25
-
-
-
-
-
- The Cracking Manual
-
-
-
- Here is what you will need to do to make the overlay
- work. First, you must find some way for the program to call
- up the overlay code. This can most easily be done by
- reprogramming interrupts. So, the first thing you have to do
- is look for an interrupt usage near the copy protection code
- (usually an INT 21h or INT 10h). When you find this
- interrupt (it must be fairly close to the code), write down
- the address of the NEXT instruction. You must get down the
- segment and the offset. Also, get down the current status of
- the registers. For interrupts like INT 21h and INT 10h,
- write down the functions numbers (eg. AX,AL,BX,DX,etc.).
- Then, keep tracing until the copy protection code. Get the
- address of the instruction that you want to change (the
- segment and the offset). Also get down the machine language
- equivalent of the changed code. This should be all you need
- for the overlay program. Here is the overlay program:
-
- INT_SEG equ 1DA5h ;SEG:OFF of instruction after the
- INT_OFF equ 05D1h ; calling interrupt
- CHANGE_SEG equ 2DA5h ;SEG:OFF of instruction to change
- CHANGE_OFF equ 0432h
-
- OVERLAY segment para 'code'
-
- assume cs:OVERLAY,ds:OVERLAY
-
- org 100h ;This will be a .COM program
-
- START: jmp INITCODE ;Initialization code
-
- ;**************************************************************************
-
- OLDINT dw 0,0 ;Storage for old interrupt address
-
- ADDR_OFF equ <word ptr [bp+2]>
- ADDR_SEG equ <word ptr [bp+4]>
-
- CR equ 0Dh ;Carriage return
- LF equ 0Ah ;Line feed
- BEEP equ 07h ;Beep
- EOS equ '$' ;End of DOS string
-
- DISPLACEMENT equ CHANGE_SEG - INTSEG
-
- ;**************************************************************************
-
- NEWINT proc far
-
- push bp ;Establish stack frame
- mov bp,sp
- push ax ;Save necessary registers
- push bx
- push cx
- push dx
-
-
- Page 26
-
-
-
-
-
- The Cracking Manual
-
-
-
- push si
- push di
- push ds
- push es
-
- mov bx,ADDR_OFF ;Get offset
- cmp bx,INT_OFF
- jnz EXIT
-
- cmp ax,0201h ;Check for AX=0201h <=(1)
- jnz EXIT
- cmp bx,0001h ;Check for BX=0001h <=(2)
- jnz EXIT
-
- mov bx,ADDR_SEG ;Get segment
- add bx,DISPLACEMENT
- mov ds,bx ;This will be the segment of change
-
- ;change the number at the next line to point to the offset of
- ; the address to be changed
- mov bx,1C12h ;This is the offset of the change
- mov al,0EBh ;This is the byte to be changed
- mov [bx],al
-
- ;change the number at the next line to point to the offset of
- ; the address to be changed
- mov bx,1C20h ;This is the new offset of the change
- mov ax,0B8h ;This is the byte to be changed
- mov [bx],ax
- mov al,0 ;This is the next byte to be changed
- mov [bx+2],al
-
- pop es ;Restore necessary registers
- pop ds
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- pop bp
- iret ;Interrupt return
-
- EXIT: pop es ;Restore necessary registers
- pop ds
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- pop bp
- jmp dword ptr cs:OLDINT ;Jump to old interrupt
-
-
-
- Page 27
-
-
-
-
-
- The Cracking Manual
-
-
-
- NEWINT endp
-
- ;**************************************************************************
-
- FINISH equ $
-
- MESSAGE db "This is an overlay loader.",CR,LF
- db "Written by The Cyborg.",CR,LF,BEEP,EOS
-
- INITCODE:
- mov ax,cs
- mov ds,ax ;DS point to CS
-
- mov ah,9 ;Print string
- mov dx,offset MESSAGE ;The address of the message
- int 21h
-
- mov ax,3510h ;Get old interrupt address
- int 21h
- mov OLDINT[0],bx ;Save in memory for later use
- mov OLDINT[2],es
-
- mov ax,2510h ;Set new interrupt address
- mov dx,offset NEWINT ;Point to new procedure
- int 21h
-
- lea dx,FINISH ;CS:DX of last byte of code to remain
- int 27h ; in memory. Terminate and stay
- ; resident.
-
- OVERLAY ends
-
- end START
-
- All you have to do is set the first four values in the first
- four lines of the file. They are the segment:offset pairs of the
- interrupt address and the address of the bytes to be changed.
- Also, change the functions to check for at (1) and (2) to
- appropriately check for proper code entry. Then, specify which
- bytes you will be changing at the specified lines. Then compile
- this crack ("ASM OVL {enter}").
- The next program demonstrates a simple loader. It also
- demonstrates what you can do if you have a program that utilizes
- scripts or dynamically allocated data areas in heap spaces. This
- program scans for a known segment in memory for a "keyword". When
- it finds this, it can then begin writing new code to overlay the
- old data. Note, KEYWORD specifies the keyword to look for. Then,
- CRK (0's) is the list of bytes to replace the data areas pointed
- to by addresses listed in LIST. The addresses in LIST are
- displacement addresses. This means that at the address the
- keyword was found in, the appropriate number listed in LIST is
- added to that address. There are thirteen addresses whose data
- are to be changed in this case.
- Also interesting to note is that this program is using two
-
-
- Page 28
-
-
-
-
-
- The Cracking Manual
-
-
-
- interrupt vectors, INT F1h and INT 21h. INT 21h is used in the
- same way as the above overlay program uses it. It replaces two
- bytes at offset 1FE5h with CDF1h. This is the machine language
- equivalent of INT F1h. Now, let's examine what INT F1h actually
- does. First, it changes the return address in the stack so that
- instead of returning to the address right after the INT F1h
- instruction, it will return to another instruction, located at
- offset 1FE5. This is the location of the INT F1h instruction.
- This interrupt, upon its completion, will replace the INT F1h
- instruction with the original instruction and run the program
- normally.
- The loader itself is simple. It reallocates the memory
- located to itself to accommodate a "daughter" program, the program
- that it is going to load. If it can't find the program or if an
- error has occurred trying to execute the program, the loader will
- load itself up as a TSR. Then, you can run the program via DOS.
- This loader also checks if INT F1h has been occupied and returns
- an error if it is.
-
- LOADER segment para 'code'
-
- assume cs:LOADER,ss:LOADER
-
- org 100h
-
- BEGIN: jmp INIT
-
- CR equ 0Dh
- LF equ 0Ah
- BEEP equ 07h
- EOLN equ '$'
-
- OPTION db 1 ;Options
- CRC dw 0 ;Cyclic Redundency Checking data
-
- START equ $
-
- OLDINT1 dw 0,0
- OLDINT2 dw 0,0
- KEYWORD db "weat"
- CRK db 0,0,0,0
- LIST dw 0h,014h,019h,02Dh,041h,046h,05Ah,05Fh,073h,087h,08Ch,0A0h,0B4h
-
- ;********** New Interrupt 1 **********;
-
- NEWINT1 proc far
-
- push bp ;Establish stack frame
- mov bp,sp
- push ax ;Save registers
- push bx
- push cx
- push dx
- push di
-
-
- Page 29
-
-
-
-
-
- The Cracking Manual
-
-
-
- push si
- push ds
-
- mov ax,cs
- mov ds,ax
-
- mov ax,word ptr [bp+2] ;Get offset
- cmp ax,1FE7h
- jnz EXIT1
-
- NEXT1: mov ax,1FE5h ;Where to return next
- mov word ptr [bp+2],ax
-
- mov ax,word ptr [bp+4] ;Get segment
- mov ds,ax ;Put in data segment
- mov bx,1FE5h ;Offset to change
- mov ax,0D803h ;The new code to put in
- mov [bx],ax ;Store changes
-
- mov ax,cs ;Get current data segment
- mov ds,ax
-
- mov di,0 ;Where to start search
- mov dx,0FF00h ;Search the entire segment
- mov bx,0
- COMP: mov di,bx ;Where to begin
- mov si,offset KEYWORD ;Get keyword
- mov cx,4 ;Lenght of keyword
- repe cmpsb ;Compare until done
- jz MATCH
- inc bx
- dec dx ;Done?
- jz EXIT1 ;If no match, exit
- jmp COMP
-
- MATCH: mov dx,bx
- mov ax,0E07h
- int 10h
- mov bx,offset LIST ;Get list of codes to change
- mov cx,13 ;Number of locations to change
- NEXT2: push cx
- mov cx,4 ;Lenght of string
- mov di,[bx] ;Get destination
- add di,dx
- mov si,offset CRK ;Get string to copy from
- rep movsb ;Copy String
- inc bx ;Next location
- inc bx
- pop cx
- loop NEXT2
-
- EXIT1: pop ds ;Restore registers
- pop si
- pop di
-
-
- Page 30
-
-
-
-
-
- The Cracking Manual
-
-
-
- pop dx
- pop cx
- pop bx
- pop ax
- pop bp
- iret ;Interrupt return
-
- NEWINT1 endp
-
- ;********** New Interrupt 2 **********;
-
- NEWINT2 proc far
-
- push bp ;Establish stack frame
- mov bp,sp
- push ax ;Save registers
- push bx
- push ds
-
- mov bx,word ptr [bp+2] ;Get offset
- cmp bx,0Ch ;See if called from the proper offset
- jnz EXIT2 ;If not, exit
-
- cmp ah,30h ;See if want this function call
- jnz EXIT2 ;If not, exit
-
- mov bx,word ptr [bp+4] ;Get segment
- add bx,0F8Dh ;New segment
- mov ds,bx
- mov bx,1FE5h ;New offset
- mov ax,0F1CDh ;The new instruction
- mov [bx],ax ;Save changes in memory
-
- EXIT2: pop ds ;Restore registers
- pop bx
- pop ax
- mov sp,bp
- pop bp
- jmp dword ptr cs:OLDINT2 ;Call old interrupt
-
- NEWINT2 endp
-
- FINISH equ $
-
- ;********** Initialization Code **********;
-
- PARAM dw 0
- db 80h,0
- PARAM1 dw 5 dup(0)
- PROG db 8 dup('1234567890')
-
- MESS db 'Savage Empire ßeta Crack v1.0 July 15,1991',CR,LF
- db 'Loader needed only after creating a character.',CR,LF
- db "Press {ENTER} at the copy protection.",CR,LF,BEEP,EOLN
-
-
- Page 31
-
-
-
-
-
- The Cracking Manual
-
-
-
- ERR1 db 'ERROR: Not enough memory. '
- db 'Activating TSR sequence.',CR,LF,BEEP,EOLN
- ERR2 db 'ERROR: Could not load program. '
- db 'Activating TSR sequence.',CR,LF,BEEP,EOLN
- ERR3 db 'ERROR: Interrupt vector (0xF1) already occupied.',CR,LF
- db ' Release memory before restarting.',CR,LF,LF,BEEP,EOLN
-
- INIT: mov ah,9 ;Print string
- mov dx,offset MESS
- int 21h
-
- mov ax,35F1h ;Get interrupt vector
- int 21h
- mov OLDINT1[0],bx ;Save in memory
- mov OLDINT1[2],es
-
- cmp word ptr es:[bx],8B55h ;Check for vector occupation
- jnz CONT1
-
- mov ah,9 ;Write string
- mov dx,offset ERR3
- int 21h
- mov ax,4C03h ;Exit with error 3
- int 21h
-
- CONT1: mov ax,25F1h ;Set interrupt vector
- mov dx,offset NEWINT1
- int 21h
-
- mov ax,3521h ;Get interrupt vector
- int 21h
- mov OLDINT2[0],bx ;Save in memory
- mov OLDINT2[2],es
-
- mov ax,2521h ;Change interrupt vector
- mov dx,offset NEWINT2
- int 21h
-
- cmp OPTION,0 ;See if wants to run program
- jz EXIT3
-
- mov ax,cs
- mov ds,ax
- mov es,ax
- mov bx,offset ENDCODE ;Get end of memory
- shr bx,1 ;Convert to paragraphs
- shr bx,1
- shr bx,1
- shr bx,1
- inc bx
- mov ah,4Ah ;Reallocate memory
- int 21h
- jnc OKAY1 ;If no error, continue
-
-
-
- Page 32
-
-
-
-
-
- The Cracking Manual
-
-
-
- mov ah,9h ;Write string
- mov dx,offset ERR1
- int 21h
- jmp EXIT3
-
- OKAY1: mov ax,cs
- mov PARAM,ax
- mov PARAM1,ax
- mov bx,offset PARAM
- mov dx,offset PROG
- mov ax,4B00h ;Load and execute child
- int 21h
- jnc OKAY2 ;If no error, continue
-
- mov ah,9h ;Write string
- mov dx,offset ERR2
- int 21h
- jmp EXIT3
-
- OKAY2: mov ax,25F1h ;Restore interrupt vector
- lds dx,dword ptr OLDINT1
- int 21h
-
- mov ax,2521h ;Restore interrupt vector
- lds dx,dword ptr OLDINT2
- int 21h
-
- mov ax,4C00h ;Exit with error code 0
- int 21h
-
- EXIT3: lea dx,FINISH ;Offset of booster
- int 27h ;Exit with ejection of booster
-
- LOADER ends
-
- end BEGIN
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 33
-
-
-
-
-
- The Cracking Manual
-
-
-
- CONCLUSION
-
- Conclusion
- ----------
- Okay, so we've seen the processes of cracking. If you are
- just a beginner and don't know much about programming, you
- probably got lost somewhere right after the introduction. I would
- suggest that you spend some time learning assembly before doing
- anything else. Actually, you don't have to start out with
- assembly. I started programming using BASIC. When I got really
- good at it, I jumped into Assembly, regardless of how difficult
- people said it was. Assembly is not at all difficult if you have
- had some previous knowledge of another language. It is only
- difficult if you make it hard. And after you've learned assembly,
- you get a "feel" for the other languages and can learn them in a
- matter of days. Pascal, Modula-2, C, C++, ..., they're are based
- on assembly language programming.
- Cracking is like the debugging process of programming. To
- become experienced with debugging is to become adept at cracking.
- You just need lots o' practice as practice makes perfect.
- One final note. I got this manual out kinda quickly so there
- are bound to be errors, inconsistencies in what I've said, unclear
- passages, etc. Well, too bad. If you really want a good manual,
- tell me or something and I'll consider it. I got really bored
- towards the last parts of the manual so it went pretty fast,
- skipping over some stuff. If a lot (and I mean A LOT) of people
- want a better manual, tell me and give me suggestions. I'll find
- the time to do it somehow.
- Anyways, have fun!
- - The Cyborg
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 34
-
-
-
-